#include "gst_enesim_buffer.h"

static GstBufferClass *enesim_buffer_parent_class = NULL;

static void
gst_enesim_buffer_finalize (GstEnesimBuffer * thiz)
{
  enesim_buffer_unref (thiz->b);
  if (thiz->rel)
    gst_buffer_unref (thiz->rel);
  GST_MINI_OBJECT_CLASS (enesim_buffer_parent_class)->finalize
      (GST_MINI_OBJECT (thiz));
}

static void
gst_enesim_buffer_init (GstEnesimBuffer * thiz, gpointer g_class)
{
}

static void
gst_enesim_buffer_class_init (gpointer g_class, gpointer class_data)
{
  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);

  enesim_buffer_parent_class = g_type_class_peek_parent (g_class);

  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
      gst_enesim_buffer_finalize;
}

static GType
gst_enesim_buffer_get_type (void)
{
  static GType _gst_enesim_buffer_type;

  if (G_UNLIKELY (_gst_enesim_buffer_type == 0)) {
    static const GTypeInfo enesim_buffer_info = {
      sizeof (GstBufferClass),
      NULL,
      NULL,
      gst_enesim_buffer_class_init,
      NULL,
      NULL,
      sizeof (GstEnesimBuffer),
      0,
      (GInstanceInitFunc) gst_enesim_buffer_init,
      NULL
    };
    _gst_enesim_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
        "GstEnesimBuffer", &enesim_buffer_info, 0);
  }
  return _gst_enesim_buffer_type;
}

GstEnesimBuffer * gst_enesim_buffer_new(Enesim_Buffer_Format format, guint width, guint height, Enesim_Pool *pool)
{
  GstEnesimBuffer *thiz;
  Enesim_Buffer *b;
  Enesim_Buffer_Sw_Data sw_data;

  /* TODO check that the pool can generate sw based buffers */
  b = enesim_buffer_new_pool_from (format, width, height, pool);
  if (!b) {
    GST_WARNING ("Impossible to create the enesim buffer of size %dx%d and format %d", width, height, format);
    return NULL;
  }

  thiz = (GstEnesimBuffer *) gst_mini_object_new (GST_TYPE_ENESIM_BUFFER);
  thiz->b = b;

  /* set the buffer data */
  enesim_buffer_data_get(b, &sw_data);
  GST_BUFFER_SIZE (thiz) = sw_data.argb8888_pre.plane0_stride * height;
  GST_BUFFER_MALLOCDATA (thiz) = (guint8 *)sw_data.argb8888_pre.plane0;
  GST_BUFFER_DATA (thiz) = GST_BUFFER_MALLOCDATA (thiz);

  return thiz;
}

GstEnesimBuffer * gst_enesim_buffer_new_from_buffer(GstBuffer *buf, Enesim_Buffer_Format format, guint width, guint height, Enesim_Pool *pool)
{
  GstEnesimBuffer *thiz;
  Enesim_Buffer *b;
  Enesim_Buffer_Sw_Data sw_data;

  /* TODO check that the pool can generate sw based buffers */
  sw_data.argb8888_pre.plane0_stride = width * 4;
  sw_data.argb8888_pre.plane0 = (uint32_t *)GST_BUFFER_DATA (buf);
  b = enesim_buffer_new_pool_and_data_from (format, width, height, pool, EINA_FALSE, &sw_data, NULL, NULL);
  if (!b) {
    /* try the copy version */
    b = enesim_buffer_new_pool_and_data_from (format, width, height, pool, EINA_TRUE, &sw_data, NULL, NULL);
    if (!b) return NULL;
  }

  thiz = (GstEnesimBuffer *) gst_mini_object_new (GST_TYPE_ENESIM_BUFFER);
  thiz->b = b;
  thiz->rel = gst_buffer_ref (buf);

  return thiz;
}
